package com.hk.core.autoconfigure.exception.reactive;

import com.hk.commons.JsonResult;
import com.hk.commons.exceptions.RepeatSubmitException;
import com.hk.commons.util.SpringContextHolder;
import org.springframework.http.HttpStatus;
import org.springframework.http.converter.HttpMessageNotReadableException;
import org.springframework.validation.BindException;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;

import java.io.FileNotFoundException;
import java.util.Objects;

/**
 * @author kevin
 * @date 2018-08-03 10:00
 */
@RestControllerAdvice
public class SimpleExceptionHandler extends AbstractExceptionHandler {

    @ExceptionHandler(value = FileNotFoundException.class)
    @ResponseStatus(HttpStatus.OK)
    public Mono<JsonResult<Void>> fileNotFountException(FileNotFoundException e, ServerWebExchange exchange) {
        error(e, e.getMessage(), exchange);
        return Mono.just(JsonResult.badRequest(SpringContextHolder.getMessage("file.not.found.message")));
    }

    /**
     * 重复表单提交
     */
    @ExceptionHandler(value = RepeatSubmitException.class)
    @ResponseStatus(HttpStatus.OK)
    public Mono<JsonResult<Void>> repeatSubmitException(RepeatSubmitException e, ServerWebExchange exchange) {
        error(e, e.getMessage(), exchange);
        return Mono.just(JsonResult.badRequest(e.getMessage()));
    }

    /**
     * 当使用 {@link org.springframework.web.bind.annotation.RequestBody} 获取请求体数据时，如果body 为 null，则抛出此异常
     *
     * @param e        e
     * @param exchange exchange
     * @return {@link JsonResult}
     */
    @ExceptionHandler(value = {HttpMessageNotReadableException.class})
    @ResponseStatus(HttpStatus.OK)
    public Mono<JsonResult<Void>> httpMessageNotReadableException(HttpMessageNotReadableException e,
                                                                  ServerWebExchange exchange) {
        error(e, e.getMessage(), exchange);
        return Mono.just(JsonResult.badRequest(SpringContextHolder.getMessage("request.body.empty.message")));
    }

    /**
     * JSR验证不通过处理
     *
     * @param e        MethodArgumentNotValidException
     * @param exchange exchange
     * @return {@link JsonResult}
     */
    @ExceptionHandler(value = {MethodArgumentNotValidException.class})
    @ResponseStatus(HttpStatus.OK)
    public Mono<JsonResult<Void>> methodArgumentNotValidException(MethodArgumentNotValidException e,
                                                                  ServerWebExchange exchange) {
        var fieldError = e.getBindingResult().getFieldError();
        var message = Objects.nonNull(fieldError) ? fieldError.getField() + fieldError.getDefaultMessage()
                : e.getMessage();
        error(e, message, exchange);
        return Mono.just(JsonResult.badRequest(message));
    }

    @ExceptionHandler(value = BindException.class)
    @ResponseStatus(HttpStatus.OK)
    public Mono<JsonResult<Void>> bindException(BindException bindException, ServerWebExchange exchange) {
        var fieldError = bindException.getBindingResult().getFieldError();
        var message = Objects.nonNull(fieldError) ? fieldError.getField() + fieldError.getDefaultMessage()
                : bindException.getMessage();
        error(bindException, message, exchange);
        return Mono.just(JsonResult.badRequest(message));
    }

    /**
     * 服务器异常
     *
     * @param e        Throwable
     * @param exchange exchange
     * @return {@link JsonResult}
     */
    @ExceptionHandler(value = {Throwable.class})
    @ResponseStatus(HttpStatus.OK)
    public Mono<JsonResult<Void>> throwable(Throwable e, ServerWebExchange exchange) {
        error(e, e.getMessage(), exchange);
        return Mono.just(JsonResult.error(e.getMessage()));
    }

}
